package cn.clx.ymcc.service.impl;

import cn.clx.ymcc.doc.CourseDoc;
import cn.clx.ymcc.domain.*;
import cn.clx.ymcc.dto.CourseDto;
import cn.clx.ymcc.feign.IMediaFeignClient;
import cn.clx.ymcc.feign.ISearchFeignClient;
import cn.clx.ymcc.mapper.CourseMapper;
import cn.clx.ymcc.result.JSONResult;
import cn.clx.ymcc.service.*;
import cn.clx.ymcc.util.AssertUtil;
import cn.clx.ymcc.util.StrUtils;
import cn.clx.ymcc.vo.CourseDetailVO;
import cn.clx.ymcc.vo.CourseInfo;
import cn.clx.ymcc.vo.OrderCourseInfoVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author clx
 * @since 2022-07-21
 */
@Service
@Transactional
@Slf4j
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    @Autowired
    private ITeacherService teacherService;
    @Autowired
    private ICourseDetailService courseDetailService;
    @Autowired
    private ICourseResourceService courseResourceService;
    @Autowired
    private ICourseMarketService courseMarketService;
    @Autowired
    private ICourseTeacherService courseTeacherService;
    @Autowired
    private ICourseTypeService courseTypeService;
    @Autowired
    private ICourseSummaryService courseSummaryService;
    @Autowired
    private ISearchFeignClient searchFeignClient;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private ICourseChapterService courseChapterService;
    @Autowired
    private IMediaFeignClient mediaFileFeignClient;
    /**
     * 新增课程，保存相关数据
     * @param dto
     */
    @Override
    public void save(CourseDto dto) {
        List<Long> teacharIds = dto.getTeacharIds();
        CourseDetail courseDetail = dto.getCourseDetail();
        CourseMarket courseMarket = dto.getCourseMarket();
        CourseResource courseResource = dto.getCourseResource();
        //校验 jsr303 校验
        //判断新增的课程是否已经存在
        Course course = dto.getCourse();
        EntityWrapper<Course> wrapper = new EntityWrapper<>();
        wrapper.eq("name",course.getName());
        Course selectOne = selectOne(wrapper);
        AssertUtil.isNull(selectOne,"该课程已经存在");

        //保存Course课程表
        saveCourse(teacharIds, course);

        //保存课程详情
        saveCourseDetail(courseDetail, course);

        //保存课程销售
        saveMarket(courseMarket, course);

        //保存课程讲师中间表
        saveCourseTeacher(teacharIds, course);

        // 保存课程资源
        saveResource(courseResource, course);

        //初始化课程统计
        saveSummary(course);

        //课程类型表中的课程数+1
        CourseType type = courseTypeService.selectById(course.getCourseTypeId());
        type.setTotalCount(type.getTotalCount() + 1);
        courseTypeService.updateById(type);
    }

    /**
     * 课程上架
     * @param id
     */
    @Override
    public void onLineCourse(Long id) {
        //首先校验 课程是否存在，课程是否已经上架了
        Course course = selectById(id);
        AssertUtil.isNotNull(course,"课程不存在");
        Integer status = course.getStatus();
        AssertUtil.isEquals(status.toString(),"0","该课程已经上架了");
        //修改状态
        course.setStatus(1);
        course.setOnlineTime(new Date());
        updateById(course);

        //调用search微服务 ，把上传的课程信息上传到es中 传递的对象是CourseDoc
        //先装CourseDoc对象
        CourseType type = courseTypeService.selectById(course.getCourseTypeId());
        CourseMarket courseMarket = courseMarketService.selectById(id);
        CourseSummary courseSummary = courseSummaryService.selectById(id);
        CourseDoc doc = new CourseDoc();
        //设置需要保存到Es的字段
        BeanUtils.copyProperties(course,doc);
        BeanUtils.copyProperties(courseMarket,doc);
        BeanUtils.copyProperties(courseSummary,doc);
        doc.setCourseTypeName(type.getName());//这里要单独赋值
        String chargeName = courseMarket.getCharge() == 1 ? "免费" : "收费";
        doc.setChargeName(chargeName);

        JSONResult result = searchFeignClient.saveES(doc);
        AssertUtil.isTrue(result.isSuccess(),"课程发布失败");

        //发送异步消息 提醒用户有新的课程上架了
        rocketMQTemplate.asyncSend("course-topic-push:course-tags-push", JSON.toJSONString(course), new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                log.info("send successful");
            }

            @Override
            public void onException(Throwable throwable) {
                log.info("send fail");
            }
        });


    }

    /**
     * 课程下架
     * @param id
     */
    @Override
    public void offLineCourse(Long id) {
        //首先校验 课程是否存在，课程是否已经上架了
        Course course = selectById(id);
        AssertUtil.isNotNull(course,"课程不存在");
        Integer status = course.getStatus();
        AssertUtil.isEquals(status.toString(),"1","该课程已经下架了");
        //修改状态
        course.setStatus(0);
        course.setOnlineTime(new Date());
        updateById(course);
        JSONResult result = searchFeignClient.deleteES(id);
        AssertUtil.isTrue(result.isSuccess(),"课程发布失败");
    }

    /**
     * 课程详情获取
     * @param id
     * @return
     */
    @Override
    public CourseDetailVO getCourseDetail(Long id) {
        Course course = selectById(id);
        AssertUtil.isNotNull(course,"课程不存在，请求非法");
        AssertUtil.isEquals(course.getStatus().toString(),"1","请求非法");
        CourseMarket courseMarket = courseMarketService.selectById(id);
        CourseDetail courseDetail = courseDetailService.selectById(id);
        CourseSummary courseSummary = courseSummaryService.selectById(id);
        EntityWrapper<CourseTeacher> wrapper = new EntityWrapper<>();
        wrapper.eq("course_id",id);
        List<CourseTeacher> courseTeachers = courseTeacherService.selectList(wrapper);
        List<Teacher> teachers = new ArrayList<>();
        courseTeachers.forEach(courseteacher->{
            teachers.add(teacherService.selectById(courseteacher.getTeacherId()));
        });

        EntityWrapper<CourseChapter> ccwrapper = new EntityWrapper<>();
        ccwrapper.eq("course_id",id);
        //该课程所对应的所有章节
        List<CourseChapter> courseChapters = courseChapterService.selectList(ccwrapper);
        courseChapters.forEach(courseChapter -> {


            //一个章节对应一个多个视频
            JSONResult jsonResult = mediaFileFeignClient.searchMediaFiles(courseChapter.getId());
            if(jsonResult.isSuccess() && jsonResult.getData() != null){
                List<MediaFile> fileList = JSONObject.parseArray(jsonResult.getData().toString(), MediaFile.class);
                fileList.forEach(mediaFile -> {
                    mediaFile.setFileUrl("");
                });
                //把视频们添加到一个章节里面
                courseChapter.getMediaFiles().addAll(fileList);
            }

        });
        CourseDetailVO vo = new CourseDetailVO();
        vo.setCourse(course);
        vo.setCourseChapters(courseChapters);
        vo.setCourseDetail(courseDetail);
        vo.setCourseMarket(courseMarket);
        vo.setCourseSummary(courseSummary);
        vo.setTeachers(teachers);
        return vo;
    }

    /**
     * 订单页面的课程信息
     * @param ids
     * @return
     */
    @Override
    public OrderCourseInfoVo getOrderCourseinfo(String ids) {
        List<Long> longs = StrUtils.splitStr2LongArr(ids);
        Set<Long> aLong = longs.stream().collect(Collectors.toSet());
        boolean size = longs.size() == aLong.size();
        AssertUtil.isTrue(size,"请求非法");
        List<CourseInfo> courseInfos = new ArrayList<>();
        BigDecimal totalAmount = new BigDecimal(0);
        for (Long id : aLong) {
            Course course = selectById(id);
            AssertUtil.isNotNull(course,"请求非法");
            boolean OK = course.getStatus() == 1;
            AssertUtil.isTrue(OK,"请求非法");
            CourseMarket courseMarket = courseMarketService.selectById(id);
            CourseInfo courseInfo = new CourseInfo(course,courseMarket);
            totalAmount=totalAmount.add(courseMarket.getPrice());
            courseInfos.add(courseInfo);
        }
        OrderCourseInfoVo vo = new OrderCourseInfoVo(courseInfos, totalAmount);
        return vo;
    }

    /**
     * 保存课程统计表
     * @param course
     */
    private void saveSummary(Course course) {
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(course.getId());
        courseSummaryService.insert(courseSummary);
    }

    /**
     * 保存课程资源表
     * @param courseResource
     * @param course
     */
    private void saveResource(CourseResource courseResource, Course course) {
        courseResource.setCourseId(course.getId());
        courseResourceService.insert(courseResource);
    }

    /**
     * 保存课程老师中间表
     * @param teacharIds
     * @param course
     */
    private void saveCourseTeacher(List<Long> teacharIds, Course course) {
        teacharIds.forEach(id->{
            CourseTeacher courseTeacher = new CourseTeacher();
            courseTeacher.setCourseId(course.getId());
            courseTeacher.setTeacherId(id);
            courseTeacherService.insert(courseTeacher);
        });
    }

    /**
     * 保存课程销售表
     * @param courseMarket
     * @param course
     */
    private void saveMarket(CourseMarket courseMarket, Course course) {
        courseMarket.setId(course.getId());
        courseMarketService.insert(courseMarket);
    }

    /**
     * 保存课程详细表
     * @param courseDetail
     * @param course
     */
    private void saveCourseDetail(CourseDetail courseDetail, Course course) {
        courseDetail.setId(course.getId());
        courseDetailService.insert(courseDetail);
    }

    /**
     * 保存课程表
     * @param teacharIds
     * @param course
     */
    private void saveCourse(List<Long> teacharIds, Course course) {
        course.setStatus(0);
        //@TODO 后面做了登录之后来补充  现在写死了
        course.setLoginId(1L);
        course.setLoginUserName("yhptest1");
        //根据老师id查到对应的老师信息
        List<Teacher> teachers = teacherService.selectBatchIds(teacharIds);

        // 整成stream
       /* Set<String> collect = teachers.stream().map(teacher -> teacher.getName()).collect(Collectors.toSet());
        String join = StringUtils.join(collect, ",");*/

        StringBuilder sb = new StringBuilder();
        //把老师的名字们组成一个字符串
        teachers.forEach(teacher -> {
            sb.append(teacher.getName()).append(",");
        });
        course.setTeacherNames(sb.toString());
        insert(course);
    }

    private Course selectByName(String name) {
        Wrapper<Course> tWrapper = new EntityWrapper<Course>();
        tWrapper.eq("name",name);
        return selectOne(tWrapper);
    }

}
